package com.nanbei.list;


import java.util.Iterator;
import java.util.function.Consumer;

/**
 * @ClassDescription: 单向链表带哨兵
 * @JdkVersion: 17
 * @Author: BaoShan.li
 * @Created: 2023/11/17 10:16
 */
public class SinglyLinkedListSentinel implements Iterable<Integer>{


    //头节点
    private Node head = new Node(999,null);


    public static class Node{
        int value;
         Node next;

        public Node(int value,  Node next) {
            this.value = value;
            this.next = next;
        }
    }

    /**
     * 在链表首位添加元素
     * @param num 添加的元素
     */
    public void addFirst(int num){
        head.next = new  Node(num,head.next);
    }


    /**
     * 链表尾部添加节点
     * @param num 添加节点的值
     */
    public void addLast(int num){

        Node last = findLast();

        last.next = new  Node(num,null);

    }

    /**
     * 查找链表的最后一个节点
     * @return 链表的最后一个节点
     */
    private  Node findLast(){

         Node node ;
        for (node = head ; node.next !=null ; ){
            node= node.next;
        }
        return node;
    }

    /**
     *  根据索引获取链表中的值
     * @param index 索引位置
     * @return 索引中的值
     * @throws IndexOutOfBoundsException   数组下标越界异常
     */
    public int get(int index) {
         Node node = findNode(index);
        if (node == null){
            throw new IndexOutOfBoundsException("所给下标过大，无数据");
        }
        return node.value;
    }

    /**
     *  根据索引添加一个元素
     * @param index 索引下标
     * @param num 添加的值
     */
    public void insert(int index,int num){

        //需要找到要插入节点的上一节点
        Node node = findNode(index - 1);
        if (node == null) {
            throw new IndexOutOfBoundsException("所给下标过大，无法新增数据");
        }

        node.next = new  Node(num, node.next);
    }

    /**
     *  根据索引下标删除一个元素
     * @param index  下标
     */
    public void del(int index){

        Node node = findNode(index-1);
        if (node != null && node.next != null){
            node.next = node.next.next;
        }else {
            throw new IndexOutOfBoundsException("所给下标过大，无法删除数据");
        }

    }


    /**
     *  根据索引查找索引所对应的节点
     * @param index 索引
     * @return 索引对应的节点
     */
    private  Node findNode(int index){
        int i = -1;
        for ( Node node = head; node!=null; node = node.next,i++){
            if (i == index){
                return node;
            }
        }
        return null;
    }


    /**
     *  while遍历链表
     */
    public void loop(){
        recursion(this.head);
    }

    /**
     *  递归遍历
     * @param node 遍历的节点
     */
    private void recursion( Node node){
        if (node == null){
            return;
        }
        System.out.println(node.value);
        recursion(node.next);
        System.out.println(node.value);


    }


    /**
     *  for遍历链表
     * @param consumer 函数式编程
     */
    public void loop2(Consumer<Integer> consumer){
        for ( Node node = head; node !=null ; node= node.next){
            consumer.accept(node.value);
        }
    }

    /**
     *  迭代器遍历链表
     * @return 节点value
     */
    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {

            //现定义一个Node指针指向头节点
             Node node = head;

            @Override
            public boolean hasNext() {
                return node != null;
            }

            @Override
            public Integer next() {
                int value = node.value;
                node = node.next;
                return value;
            }
        };
    }

}
